import { Component, OnInit, TemplateRef } from '@angular/core';
import { EurekaManageService } from 'src/app/services/eureka-manage/eureka-manage.service';
import * as _ from 'lodash';
import { EurekaApplication } from 'src/app/entity/eureka-manage/eureka-application';
import { EurekaInstance } from 'src/app/entity/eureka-manage/eureka-instance';
import { Subject, pipe } from 'rxjs';
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators';
import { Eureka } from 'src/app/entity/eureka-manage/eureka';
import { EurekaRegisterService } from 'src/app/services/eureka-manage/eureka-register.service';
import {NzNotificationService} from 'ng-zorro-antd/notification';
import {NzModalRef, NzModalService} from 'ng-zorro-antd/modal';

/**
 * localStorage 引用
 */
const storage = localStorage;

/**
 * Eureka Applications Dashboard Component
 */
@Component({
  selector: 'app-applications',
  templateUrl: './applications.component.html',
  styleUrls: ['./applications.component.less']
})
export class ApplicationsComponent implements OnInit {

  /**
   * 页面展示的栅格数据
   */
  eurekaApplicationsGroup: EurekaApplication[][];
  /**
   * 当前展示详情的Eureka Instance
   */
  currentShowInstance: EurekaInstance = null;
  /**
   * 当前展示详情的Eureka Instance Json数据
   */
  currentShowInstanceJson: string = null;
  /**
   * 页面加载中标志
   */
  loading = false;
  /**
   * 是否自动刷新
   */
  autoRefresh: boolean;
  /**
   * 应用名称搜索参数
   */
  applicationNameSearchParam: string;
  /**
   * 有效Eureka集合
   */
  eurekaList: Eureka[];
  /**
   * eureka code
   */
  eurekaCode: string;
  /**
   * eureka code是否已就绪
   */
  eurekaCodeIsReady = false;

  /**
   * 当前持有的所有Eureka Application
   */
  private eurekaApplications: EurekaApplication[];
  /**
   * 自动刷新触发器
   */
  private autoRefreshHandler: any;
  /**
   * 应用名称搜索防抖处理流
   */
  private applicationNameSearchParam$ = new Subject<string>();

  constructor(private eurekaManageService: EurekaManageService, // Eureka管理Service
              private notificationService: NzNotificationService, // 消息弹窗Service
              private modalService: NzModalService, // Model Service
              private eurekaRegisterService: EurekaRegisterService, // Eureka Register Service
  ) { }


  /**
   * 组件初始化
   */
  ngOnInit() {
    this.eurekaCodeIsReady = false;
    // 查询可用Eureka
    this.eurekaRegisterService.getAllEureka().subscribe(data => {
      this.eurekaList = data;
      // 判断local storage缓存的值是否是合法值
      // 如果有, 则自动锁定这个eureka code
      const eurekaCodeInStorage = storage.getItem('eurekaCode');
      if (!!eurekaCodeInStorage && this.validateEurekaCode(eurekaCodeInStorage)) {
        this.eurekaCode = eurekaCodeInStorage;
        this.toggleEurekaCodeIsReady();
      } else {
        storage.setItem('eurekaCode', '');
      }
    });
    // 应用名称搜索防抖处理流注册
    this.applicationNameSearchParam$.pipe(
      debounceTime(500),
      distinctUntilChanged(),
      map(applicationNameSearchParam => this.filterApplications(applicationNameSearchParam))
    ).subscribe();
  }

  /**
   * 查询Eureka数据
   */
  loadData = () => {
    if (!this.eurekaCodeIsReady) {
      this.notificationService.error('警告', '请先选择要操作的Eureka');
      return;
    }
    this.loading = true;
    this.eurekaManageService.getAllEurekaApplications(this.eurekaCode)
      .subscribe(data => {
        data = !!data ? data : [];
        this.eurekaApplications = data;
        this.eurekaApplicationsGroup = _.chunk(this.eurekaApplications, 3);
        this.filterApplications(this.applicationNameSearchParam);
        this.loading = false;
      });
  }


  /**
   * Instance上线
   *
   * @param applicationName 上线应用名称
   * @param instanceId 上线实例名称
   */
  putStatusUp = (applicationName: string, instanceId: string) => {
    if (!this.eurekaCodeIsReady) {
      this.notificationService.error('警告', '请先选择要操作的Eureka');
      return;
    }
    this.eurekaManageService.putStatusUp(this.eurekaCode, applicationName, instanceId).subscribe(data => {
      this.notificationService.success('操作成功', '处理结果展示将存在一定延迟');
      this.loadData();
    });
  }

  /**
   * Instance下线
   *
   * @param applicationName 下线应用名称
   * @param instanceId 下线实例名称
   */
  putStatusOutOfService = (applicationName: string, instanceId: string) => {
    if (!this.eurekaCodeIsReady) {
      this.notificationService.error('警告', '请先选择要操作的Eureka');
      return;
    }
    this.eurekaManageService.putStatusOutOfService(this.eurekaCode, applicationName, instanceId).subscribe(data => {
      this.notificationService.success('操作成功', '处理结果展示将存在一定延迟');
      this.loadData();
    });
  }

  /**
   * 打开详情弹窗
   *
   * @param instance 当前展示详情的Eureka Instance
   * @param instanceDetailContentTemplate 弹窗Content模板引用
   */
  openInstanceDetail = (instance: EurekaInstance, instanceDetailContentTemplate: TemplateRef<{}>) => {
    if (!instance) {
      return;
    }
    this.currentShowInstance = instance;
    this.currentShowInstanceJson = JSON.stringify(this.currentShowInstance, null, 4);
    const modalRef: NzModalRef = this.modalService.create({
      nzTitle: instance.instanceId,
      nzContent: instanceDetailContentTemplate,
      nzFooter: null,
      nzWidth: '60%',
    });
    modalRef.afterClose.subscribe(data => {
      this.currentShowInstance = null;
      this.currentShowInstanceJson = null;
    });
  }

  /**
   * 自动刷新属性变更Handler
   *
   * @param event 是否自动刷新
   */
  autoRefreshChangeHandler = (event: boolean) => {
    this.autoRefresh = event;
    // save to localStorage
    storage.setItem('autoRefresh', this.autoRefresh ? 'true' : 'false');
    if (this.autoRefresh) {
      this.autoRefreshHandler = setInterval(() => {
        this.loadData();
      }, 5000);
    } else {
      clearInterval(this.autoRefreshHandler);
    }
  }

  /**
   * Application Name查询条件变更Handler
   *
   * @param applicationNameSearchParam Application Name查询条件
   */
  applicationNameSearchParamChangeHandler = (applicationNameSearchParam: string) => {
    this.applicationNameSearchParam$.next(applicationNameSearchParam);
  }

  /**
   * 切换eureka的绑定状态并处理相应事项
   */
  toggleEurekaCodeIsReady = () => {
    if (!this.eurekaCodeIsReady) {
      // 切换至锁定状态
      if (_.isEmpty(this.eurekaCode)) {
        this.notificationService.error('警告', '请先选择要操作的Eureka');
        return;
      }
      this.eurekaCodeIsReady = true;
      storage.setItem('eurekaCode', this.eurekaCode);
      // 查询Eureka数据
      this.loadData();
      // 从localStorage中查询是否需要开启自动刷新
      this.autoRefresh = storage.getItem('autoRefresh') === 'true';
      if (this.autoRefresh) {
        this.autoRefreshChangeHandler(true);
      }
    } else {
      this.eurekaCodeIsReady = false;
      storage.setItem('eurekaCode', '');
      this.autoRefreshChangeHandler(false);
      this.eurekaApplicationsGroup = [];
    }
  }

  /**
   * Application Name查询条件变更Handler
   *
   * @param applicationNameSearchParam Application Name查询条件
   */
  private filterApplications = (applicationNameSearchParam: string) => {
    let filterResult: EurekaApplication[];
    if (_.isEmpty(applicationNameSearchParam)) {
      filterResult = this.eurekaApplications;
    } else {
      filterResult = _.filter(this.eurekaApplications, (application) =>
        application.name.indexOf(applicationNameSearchParam.toUpperCase()) !== -1
      );
    }
    this.eurekaApplicationsGroup = _.chunk(filterResult, 3);
  }

  /**
   * 校验eureka code是否合法
   * @param eurekaCode eureka code
   */
  private validateEurekaCode = (eurekaCode: string) => {
    for (const eureka of this.eurekaList) {
      if (eureka.code === eurekaCode) {
        return true;
      }
    }
    return false;
  }

}
